package com.demon.auto.interceptor;

import com.alibaba.fastjson2.JSON;
import com.baomidou.mybatisplus.core.toolkit.StringUtils;
import com.demon.auto.constant.CommonConstant;
import com.demon.auto.model.ApiResponseModel;
import com.demon.auto.model.dto.SignClientDto;
import com.demon.auto.service.SignClientService;
import com.demon.auto.utils.JwtUtil;
import lombok.extern.slf4j.Slf4j;
import org.springframework.beans.factory.annotation.Autowired;
import org.springframework.http.HttpHeaders;
import org.springframework.http.HttpStatus;
import org.springframework.http.server.ServerHttpRequest;
import org.springframework.http.server.ServerHttpResponse;
import org.springframework.http.server.ServletServerHttpRequest;
import org.springframework.stereotype.Component;
import org.springframework.web.socket.WebSocketHandler;
import org.springframework.web.socket.server.HandshakeInterceptor;

import javax.servlet.http.HttpServletRequest;
import java.io.IOException;
import java.util.Map;

/**
 * websocket拦截器
 *
 * @version 1.0
 * @author huangrz
 * @date 2025/02/13 14:18
 */
@Slf4j
@Component
public class WebSocketAuthInterceptor implements HandshakeInterceptor {

    @Autowired
    private SignClientService signClientService;

    /**
     * 连接前处理
     * ws://127.0.0.1:8080/ws/sign?clientName=DemonRedmi6Pro&token=eyJhbGciOiJIUzUxMiJ9.eyJqdGkiOiIxZWNkYTgxMmZmMTA0YjgxYjM4ZDNkYWNmODhjMjEzNCIsInN1YiI6ImFkbWluIiwiaXNzIjoiYWRtaW4iLCJpYXQiOjE3Mzk3NjI0NTZ9.2tFl40FuizhG76VAze8SnlzGMe58E9WZzcEGVJRHwevGZm5pSMSvHjvxNoTNeXJ4WfZODzUIYsrjiR2FiH6HsA
     * @param request       请求
     * @param response      响应
     * @param wsHandler     处理器
     * @param attributes    属性
     * @return boolean 是否连接
     */
    @Override
    public boolean beforeHandshake(ServerHttpRequest request,
                                   ServerHttpResponse response,
                                   WebSocketHandler wsHandler,
                                   Map<String, Object> attributes) {
        // 从请求参数获取Token
        if (!(request instanceof ServletServerHttpRequest)) {
            log.error("参数 request 不是 ServletServerHttpRequest 类型");
            buildResponseResult(response, "参数 request 不是 ServletServerHttpRequest 类型");
            return false;
        }

        HttpServletRequest servletRequest = ((ServletServerHttpRequest) request).getServletRequest();
        String clientName = servletRequest.getParameter(CommonConstant.PARAM_CLIENT_NAME);
        if (StringUtils.isBlank(clientName)) {
            log.error("websocket客户端名称为空");
            buildResponseResult(response, "websocket客户端名称为空");
            return false;
        }

        // 验证Token有效性
        String token = servletRequest.getHeader(CommonConstant.PARAM_TOKEN);
        if (StringUtils.isBlank(token)) {
            token = servletRequest.getParameter(CommonConstant.PARAM_TOKEN);
        }
        if (!JwtUtil.EXEMPTION_TOKEN.equals(token) && !JwtUtil.isTokenValid(token)) {
            log.warn("token已过期");
            // 验证失败拒绝连接
            buildResponseResult(response, "token已过期");
            return false;
        }

        String username = JwtUtil.getUsernameByToken(token);
        if (StringUtils.isBlank(username)) {
            log.error("token无效");
            // 验证失败拒绝连接
            buildResponseResult(response, "token无效");
            return false;
        }

        // 校验签到客户端
        if (!clientName.contains(CommonConstant.PAGE_CLIENT_NAME_CONTAINS)) {
            SignClientDto signClientDto = signClientService.getSignClientByClientName(clientName);
            if (signClientDto == null) {
                String info = "客户端不存在：" + clientName;
                log.error(info);
                buildResponseResult(response, info);
                return false;
            }
            // 存储签到客户端信息
            attributes.put(CommonConstant.PARAM_CLIENT_INFO, signClientDto);
        }

        // 存储token用户名
        attributes.put(CommonConstant.PARAM_USERNAME, username);
        // 存储客户端名称
        attributes.put(CommonConstant.PARAM_CLIENT_NAME, clientName);
        return true;
    }

    /**
     * 连接后处理
     * @param request   请求
     * @param response  响应
     * @param wsHandler 处理器
     * @param exception 异常
     */
    @Override
    public void afterHandshake(ServerHttpRequest request,
                               ServerHttpResponse response,
                               WebSocketHandler wsHandler,
                               Exception exception) {
    }


    private void buildResponseResult(ServerHttpResponse response, String msg) {
        try {
            response.setStatusCode(HttpStatus.OK);
            response.getHeaders().add(HttpHeaders.CONTENT_TYPE, "application/json;charset=UTF-8");
            response.getBody().write(JSON.toJSONString(ApiResponseModel.unauthorized(msg)).getBytes());
        } catch (IOException e) {
            throw new RuntimeException(e);
        }
    }

}